package cn.s1995.sloth.common.core.util;


import cn.hutool.core.date.LocalDateTimeUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.hutool.core.date.DatePattern.NORM_DATETIME_PATTERN;


public class DateUtil {


    public final static String yyyyMMdd = "yyyy-MM-dd";
    public final static String yyyyMMddHH = "yyyy-MM-dd HH";
    public final static String yyyyMMddHHmm = "yyyy-MM-dd HH:mm";
    public final static String yyyyMMddHHmmss = "yyyy-MM-dd HH:mm:ss";

    public final static String FORMAT_PATTERN1 = "yyyy-MM-dd HH:mm:ss";
    public final static String FORMAT_PATTERN2 = "yyyyMMddHHmmss";
    public final static String FORMAT_PATTERN3 = "yyyy-MM-dd";
    public final static String FORMAT_PATTERN4 = "yyyyMMdd";
    public final static String FORMAT_PATTERN5 = "HH:mm:ss";
    public final static String FORMAT_PATTERN6 = "yyyy-MM";
    public final static String FORMAT_PATTERN7 = "dd MMMM yyyy HH:mm:ss";

    public final static String FORMAT_PATTERN8 = "yyyy-MM";

    /**
     * 日期格式yyyy-MM-dd
     */
    public static String DATE_PATTERN = "yyyy-MM-dd";

    /**
     * 日期时间格式yyyy-MM-dd HH:mm:ss
     */
    public static String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 日期时间格式yyyy/MM/dd HH:mm:ss SSS
     */
    public static String DATE_MSEL_TIME_PATTERN = "yyyy/MM/dd HH:mm:ss SSS";
    /**
     * rfc3339标准格式时间yyyy-MM-dd'T'HH:mm:ssXXX
     */
    public static String RFC3339_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ssXXX";

    public static DateTimeFormatter DF = java.time.format.DateTimeFormatter.ofPattern(FORMAT_PATTERN1);


    /**
     * 单位
     */
    public interface Unit {
        String hour = "hour";
        String day = "day";
    }

    public static void main(String[] args) {
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //Date beginDayOfWeek = getBeginDayOfWeek();
        //System.out.println("本周开始时间"+beginDayOfWeek);
        //Date endDayOfWeek = getEndDayOfWeek();
        //System.out.println("本周结束时间"+endDayOfWeek);
        //
        //Date beginDayOfLastWeek = getBeginDayOfLastWeek();
        //System.out.println("上周开始时间"+beginDayOfLastWeek);
        //
        //Date endDayOfLastWeek = getEndDayOfLastWeek();
        //System.out.println("上周结束时间"+sdf.format(endDayOfLastWeek));

        //System.out.println(getOneYear());
        //System.out.println(getTargetYear(new Date(), -1));

//        String s = secondToTime(160000L);
//        System.out.println(s);


        // System.out.println(parse("2024-04-01 10", yyyyMMddHH));


        // getAroundRangeTime
        //         (new String[]{"2024-04-01 10:00", "2024-04-02 09"}, Unit.hour)
        //         .forEach(System.out::println);
        //
        // System.out.println("====================================");
        //
        // getAroundRangeTime
        //         (new String[]{"2024-04-01 00:00:00", "2024-04-02 00:00:00"}, Unit.day)
        //         .forEach(System.out::println);
        //


        System.out.println(getTodayRemainingTime());
    }



    /**
     * 字符串日期转日期
     *
     * @param time    时间字符串 "2017-05-23"
     * @param pattern 时间字符串格式 默认"yyyy-MM-dd"
     * @return
     */
    public static Date stringToDate(String time, String pattern) {
        try {
            if (pattern == null || "".equals(pattern)) {
                pattern = "yyyy-MM-dd";
            }
            SimpleDateFormat sdf = new SimpleDateFormat(pattern);
            return sdf.parse(time);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }







    /**
     * 返回日时分秒
     *
     * @param second
     * @return
     */
    public static String secondToTime(long second) {
        //转换小时数
        long hours = second / 3600;
        //剩余秒数
        second = second % 3600;
        //转换分钟
        long minutes = second / 60;
        //剩余秒数
        second = second % 60;
        return hours + "h " + minutes + "m " + second + "s";
    }

    /**
     * 按pattern格式化时间-默认yyyy-MM-dd HH:mm:ss格式
     *
     * @param dateTime LocalDateTime对象
     * @param pattern  要格式化的字符串
     * @return
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        if (dateTime == null) {
            return null;
        }
        if (pattern == null || pattern.isEmpty()) {
            pattern = DATE_TIME_PATTERN;
        }
        DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(pattern);
        return dateTime.format(formatter);
    }

    /**
     * 按pattern格式化时间-默认yyyy-MM-dd HH:mm:ss格式
     *
     * @param dateTime LocalDateTime对象
     * @return
     */
    public static String format(LocalDateTime dateTime) {
        return format(dateTime, DATE_TIME_PATTERN);
    }


    /**
     * 按pattern格式化时间-默认yyyy-MM-dd HH:mm:ss格式
     *
     * @param dateTime LocalDate对象
     * @param pattern  要格式化的字符串
     * @return
     */
    public static String format(LocalDate dateTime, String pattern) {
        if (dateTime == null) {
            return null;
        }
        if (pattern == null || pattern.isEmpty()) {
            pattern = DATE_PATTERN;
        }
        DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(pattern);
        return dateTime.format(formatter);
    }

    /**
     * 按pattern格式化时间-默认yyyy-MM-dd HH:mm:ss格式
     *
     * @param dateTime LocalDate对象
     * @return
     */
    public static String format(LocalDate dateTime) {
        return format(dateTime, DATE_PATTERN);
    }




    /**
     * 转换时间
     * @param time
     * @return
     */
    public static LocalDateTime parse(String time) {
        return parse(time, DF);
    }

    /**
     * 转换时间
     * @param time
     * @return
     */
    public static LocalDateTime parse(String time, String pattern) {
        return parse(time, java.time.format.DateTimeFormatter.ofPattern(pattern));
    }


    /**
     * 转换时间
     * @param time
     * @return  LocalDateTime
     */
    public static LocalDateTime parse(String time, DateTimeFormatter dateTimeFormatter) {
        if (time == null || time.isEmpty()) {
            return null;
        }
        return LocalDateTime.parse(time, dateTimeFormatter);
    }

    /**
     * 转换时间
     * @param time 时间字符串
     * @param dateTimeFormatter 时间格式化器
     * @param clazz 返回对象的类类型
     * @return 转换后的日期对象
     */
    public static <T> T parse(String time, DateTimeFormatter dateTimeFormatter, Class<T>... clazz) {
        if (time == null || time.isEmpty()) {
            return null;
        }
        if (clazz == null || clazz.length == 0) {
            return (T) LocalDateTime.parse(time, dateTimeFormatter);
        }

        if (clazz[0] == LocalDate.class) {
            return clazz[0].cast(LocalDate.parse(time, dateTimeFormatter));
        } else if (clazz[0] == LocalDateTime.class) {
            return clazz[0].cast(LocalDateTime.parse(time, dateTimeFormatter));
        } else {
            throw new IllegalArgumentException("Unsupported class type for parsing");
        }
    }



    /**
     * 获取时间范围
     *
     * @param rangeTime 时间范围字符串数组
     * @param unit
     * @return 返回格式化的日期字符串列表
     */
    public static List<String> getAroundRangeTime(String[] rangeTime, String unit) {
        if (rangeTime == null || rangeTime.length < 1) {
            return new ArrayList<>();
        }
        List<String> res = new ArrayList<>();
        if (Unit.hour == unit) {
            String formatter = yyyyMMddHH;
            // 解析起始和结束日期
            LocalDateTime start = parse(rangeTime[0].substring(0, formatter.length()), formatter);
            LocalDateTime end = parse(rangeTime[1].substring(0, formatter.length()), formatter);
            res = Stream.iterate(start, item -> item.plusHours(1))
                    .limit(start.until(end, ChronoUnit.HOURS) + 1)
                    .map(item -> format(item, formatter))
                    .collect(Collectors.toList());
        }
        if (Unit.day == unit) {
            String formatter = yyyyMMdd;
            // 解析起始和结束日期
            LocalDate start = parse(rangeTime[0].substring(0, formatter.length()), DateTimeFormatter.ofPattern(formatter), LocalDate.class);
            LocalDate end = parse(rangeTime[1].substring(0, formatter.length()), DateTimeFormatter.ofPattern(formatter), LocalDate.class);
            res = Stream.iterate(start, item -> item.plusDays(1))
                    .limit(start.until(end, ChronoUnit.DAYS) + 1)
                    .map(item -> format(item, formatter))
                    .collect(Collectors.toList());
        }

        return res;
    }


    /**
     * 判断是否是日期范围&时间是否有效
     *
     * @return
     */
    public static boolean isRangeTime(String[] array) {
        boolean b = array != null && array.length == 2;
        boolean b2 = Boolean.FALSE;
        if (b) {
            DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN);
            LocalDateTime start = LocalDateTimeUtil.parse(array[0], formatter);
            LocalDateTime end = LocalDateTimeUtil.parse(array[1], formatter);
            // 存在两个时间&&(开始时间要在结束时间之前||两个时间相等)
            b2 = (start.isBefore(end) || start.isEqual(end));
        }

        return b && b2;
    }

    /**
     * 判断是否是同一天
     *
     * @return
     */
    public static boolean isSameDay(String[] array) {
        boolean b = array != null && array.length == 2;
        boolean b2 = Boolean.FALSE;
        boolean b3 = Boolean.FALSE;
        if (b) {
            DateTimeFormatter formatter = java.time.format.DateTimeFormatter.ofPattern(NORM_DATETIME_PATTERN);
            LocalDateTime start = LocalDateTimeUtil.parse(array[0], formatter);
            LocalDateTime end = LocalDateTimeUtil.parse(array[1], formatter);
            // 存在两个时间&&(开始时间要在结束时间之前||两个时间相等)
            b2 = (start.isBefore(end) || start.isEqual(end));

            // 是同一天
            b3 = LocalDateTimeUtil.isSameDay(start, end);
        }

        return b && b2 && b3;
    }

    /**
     * 获取当天剩余时间
     *
     * @return
     */
    public static long getTodayRemainingTime(ChronoUnit... unit) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime end = LocalDateTime.of(now.toLocalDate(), LocalDateTime.MAX.toLocalTime());
        if (unit != null && unit.length > 0) {
            return now.until(end, unit[0]);
        } else {
            return now.until(end, ChronoUnit.SECONDS);
        }
    }


    /**
     * 增加或减少年/月/周/天/小时/分/秒数
     *
     * @param localDateTime
     * @param chronoUnit    单位 例：ChronoUnit.DAYS
     * @param val           值
     * @return LocalDateTime
     */
    public static LocalDateTime plus(LocalDateTime localDateTime, ChronoUnit chronoUnit, int val) {
        return localDateTime.plus(val, chronoUnit);
    }
}
